---
title: Using Context
description: Guide for using context object in Pothos
---

The GraphQL context object can be used to give every resolver in the schema access to some shared
state for the current request. One common use case is to store the current User on the context
object.

One important thing to note about Pothos is that every request is assumed to have a new unique
context object, so be sure to set up your context objects in a way that they are unique to each
request.

First let's define a User class that holds information about a user, and create a SchemaBuilder with
a Context type that has a currentUser property.

```typescript
class User {
  id: string;
  firstName: string;
  username: string;

  constructor(id: string, firstName: string, username: string) {
    this.id = id;
    this.firstName = firstName;
    this.username = username;
  }
}

const builder = new SchemaBuilder<{
  Context: {
    currentUser: User;
  };
}>({});
```

Next, we will want to add something in our schema that uses the current user:

```typescript
builder.queryType({
  fields: (t) => ({
    currentUser: t.field({
      type: User,
      resolve: (root, args, context) => context.currentUser,
    }),
  }),
});

builder.objectType(User, {
  fields: (t) => ({
    id: t.exposeID('id', {}),
    firstName: t.exposeString('firstName', {}),
    username: t.exposeString('username', {}),
  }),
});
```

Finally, we need to actually create our context when a request is created.

```typescript
const yoga = createYoga({
  schema,
  context: async ({ req }) => ({
    // This part is up to you!
    currentUser: await getUserFromAuthHeader(req.headers.authorization),
  }),
});
const server = createServer(yoga);

server.listen(3000);
```

## Initialize context cache

Several Pothos plugins use the context object to cache data for the current request. Some examples
include dataloaders and auth scopes. This caching mechanism works based on the assumption that the
same context object is passed to every resolver in a request, and each request has a unique context
object. This works for most applications without any additional configuration.

In some rare edge cases, you may have some additional logic added to your application that clones or
mutates the context object throughout the execution of a request. To ensure that all plugins work
correctly even if the context object is cloned, wrapped, or modified in a way that does not preserve
its identity, you can manually initialize the context cache and attach it to the context object:

```typescript
import { initContextCache } from '@pothos/core';

const server = createYoga({
  schema: builder.toSchema(),
  context: async ({ req }) => ({
    // Adding this will prevent any issues if you server implementation
    // copies or extends the context object before passing it to your resolvers
    ...initContextCache(),

    currentUser: await getUserFromAuthHeader(req.headers.authorization),
  }),
});

const server = createServer(yoga);

server.listen(3000);
```

## Context when using multiple protocols

In some specific situations multiple protocols could be used for handling the graphql operations against the same executable graphql schema. One common example of this is using [HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP)(Hypertext Transfer Protocol) protocol for handling graphql query and mutation operations and using [Websocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) protocol for handling graphql subscription operations. Because the protocols are different, the protocol specific information that might be passed in the graphql context could differ depending on the graphql operation that is being executed. **Now, our personal recommendation is to keep your executable graphql schema and its inner layers protocol agnostic to not have to deal with a situation like this.**

We're working with two different graphql contexts within our graphql resolvers and we want strong type-safety while working with them. For this use case we recommend using [typescript discriminated unions](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions) for combining types for different graphql contexts into a single union type that can be passed to pothos schema builder initializer. In the following example `Context` is a union type between graphql context types for HTTP and Websocket protocol specific graphql contexts, where the `isSubscription` boolean field is the discriminator. This context type is passed as the type for `Context` field in the generic accepted by the pothos schema builder initializer. Within the resolver implementations for a graphql schema created using this pothos schema builder, the graphql context can be discriminated between its two protocol specific types by using the `isSubscription` field. This would help us get the type-safe graphql context that we can make use of in our graphql resolvers. In the following code we perform this discrimination by checking the value of `isSubscription` boolean field in the `if` and `else` blocks within the graphql resolvers:

```typescript
type Context =
  | {
      isSubscription: false;
      http: "HTTP specific context field."
    }
  | {
      isSubscription: true;
      websocket: "Websocket specific context field.";
    };

const builder = new SchemaBuilder<{
  Context: Context;
}>({});

builder.mutationType({
  fields: (t) => ({
    incrementCount: t.int({
      resolve: (parent, args, ctx) => {
        if (ctx.isSubscription === false) {
          // Access the HTTP protocol specific context fields.
          ctx.http;
        } else {
          // Access the Websocket protocol specific context fields.
          ctx.websocket;
        }
      },
    }),
  }),
});

builder.subscriptionType({
  fields: (t) => ({
    currentCount: t.int({
      subscribe: (parent, args, ctx) => {
        if (ctx.isSubscription === false) {
          // Access the HTTP protocol specific context fields.
          ctx.http;
        } else {
          // Access the Websocket protocol specific context fields.
          ctx.websocket;
        }
      },
    }),
  }),
});
```
